#include <stdio.h>
#include <pspkernel.h>
#include <pspdisplay.h>
#include <string.h>
#include <math.h>
#include <psputility.h>
#include <pspgu.h>
#include <pspgum.h>
#include <pspsdk.h>
#include <pspnet.h>
#include <pspnet_inet.h>
#include <pspnet_apctl.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sstream>
#include <string>

#include "Network.h"
#include "DefGU.h"
#include "opcodes.h"


Network::Network(Graph* gu)	
{
	graph = gu;

	sceUtilityLoadNetModule(PSP_NET_MODULE_COMMON);

	sceUtilityLoadNetModule(PSP_NET_MODULE_INET);

	sceNetInit(128*1024, 42, 4*1024, 42, 4*1024);

	sceNetInetInit();

	sceNetApctlInit(0x8000, 48);
}

Network::~Network()	
{
	sceNetApctlTerm();
	
	sceNetInetTerm();
	
	sceNetTerm();
}
	
int Network::netDialog()
	{
		int done = 0;		

   		pspUtilityNetconfData data;

		memset(&data, 0, sizeof(data));
		data.base.size = sizeof(data);
		data.base.language = PSP_SYSTEMPARAM_LANGUAGE_ENGLISH;
		data.base.buttonSwap = PSP_UTILITY_ACCEPT_CROSS;
		data.base.graphicsThread = 17;
		data.base.accessThread = 19;
		data.base.fontThread = 18;
		data.base.soundThread = 16;
		data.action = PSP_NETCONF_ACTION_CONNECTAP;
		
		struct pspUtilityNetconfAdhoc adhocparam;
		memset(&adhocparam, 0, sizeof(adhocparam));
		data.adhocparam = &adhocparam;

		sceUtilityNetconfInitStart(&data);
		
		while(1)
		{		
			graph->RefreshScreen(0xff554433);

			switch(sceUtilityNetconfGetStatus())
			{
				case PSP_UTILITY_DIALOG_NONE:
					break;

				case PSP_UTILITY_DIALOG_VISIBLE:
					sceUtilityNetconfUpdate(1);
					break;

				case PSP_UTILITY_DIALOG_QUIT:
					sceUtilityNetconfShutdownStart();
					break;
					
				case PSP_UTILITY_DIALOG_FINISHED:
					done = 1;
					break;

				default:
					break;
			}

			sceDisplayWaitVblankStart();
			sceGuSwapBuffers();
			
			if(done)
				break;
		}	
		return 1;
	}

bool Network::Connect()
	{		
		int ret;
		struct sockaddr_in name;
		char buffer[4096];
		int flag;

		sock = sceNetInetSocket(PF_INET, SOCK_STREAM, 0);
		if (sock < 0)
		{
			return false;
		}

		name.sin_family = AF_INET;
		name.sin_port = htons(2222);
		name.sin_addr.s_addr = sceNetInetInetAddr("192.168.2.158");

		flag = 1;
		ret = sceNetInetSetsockopt(sock, 0xFFFF, SO_NONBLOCK, &flag, sizeof(flag));
		if (ret < 0)
		{
			return false;
		}

		ret = sceNetInetConnect(sock, (struct sockaddr *) &name, sizeof(name));
		if (ret < 0)
		{
			if (sceNetInetGetErrno() == 119)
			{
			}
			else
			{			
				return false;
			}
		}	

		//while (1)
		//{
		//	int length = sceNetInetRecv(sock, buffer, sizeof(buffer), 0);
		//	if (length < 0 && sceNetInetGetErrno() == 11)
		//	{
		//		// wait a little before polling again
		//		sceKernelDelayThread(100*1000); // 100ms
		//	}
		//	else
		//	{
		//		if (length >= 0)
		//		{
		//			buffer[length] = '\0';
		//		}
		//		break;
		//	}
		//}
		//strcpy(buffer + 100, "...");		
	}
void Network::Disconnect()
{
	sceNetInetClose(sock);
}

void Network::SendData(Opcode opcode,char *cmd)
{	
	int opint = (int) opcode;
	char opchr[sizeof(opint)];	
	sprintf(opchr,"%i",opint);

	char packet[sizeof(cmd)+sizeof(opchr)];

	sprintf(packet,"%s%s",opchr,cmd);
	
	while (1)
	{		
		int length = sceNetInetSend(sock, packet, strlen(packet), 0);
		if (length < 0 && sceNetInetGetErrno() == 128)
		{
			// wait a little before polling again
			sceKernelDelayThread(500*1000); // 500ms
		}
		else
		{
			break;
		}
	}
}

void Network::Encode(char *msg)
{	
	
}